package vg.userInterface.jgraphx;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Map;
import java.util.Observable;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxUtils;
import com.mxgraph.view.mxStylesheet;
import vg.core.AMenuItem;
import vg.core.VisualGraph;
import vg.core.exception.PluginException;
import vg.core.plugin.IPlugin;
import vg.core.plugin.PluginParameter;
import vg.userInterface.swingComponents.FontChooserComboBox;
public class JGraphSettings implements IPlugin{
private boolean inited = false;
private static int spacingLeft;
private static int spacingTop;
private static int spacingRight;
private static int spacingBottom;
private static String fontColor;
private static String fillColor;
private static String vertexShape;
private static String graphElemetsFont;
private static String vertexTextAlign;
private static ArrayList<ActionListener> listners = new ArrayList<ActionListener>();
private static mxStylesheet stylesheet = new mxStylesheet();
private final static String CONF_VERTEX_SPACING_LEFT = "vertex_spacing_left";
private final static String CONF_VERTEX_SPACING_TOP = "vertex_spacing_top";
private final static String CONF_VERTEX_SPACING_RIGHT = "vertex_spacing_right";
private final static String CONF_VERTEX_SPACING_BOTTOM = "vertex_spacing_bottom";
private final static String CONF_VERTEX_FONT_COLOR = "vertex_font_color";
private final static String CONF_VERTEX_FILL_COLOR = "vertex_fill_color";
private final static String CONF_VERTEX_SHAPE = "vertex_shape";
private final static String CONF_GRAPH_ELEMENTS_FONT = "graph_elements_font";
private final static String CONF_VERTEX_TEXT_ALIGN = "vertex_text_align";
//----------- SWING-------------------
private JComponent[] dialogComponents = null;
private FontChooserComboBox fontChooser = null;
private IntegerDocumentListner spacingLeftDoc = null;
private IntegerDocumentListner spacingTopDoc = null;
private IntegerDocumentListner spacingBottomDoc = null;
private IntegerDocumentListner spacingRightDoc = null;
private ColorPreview fontColorPreview = null;
private ColorPreview vertexColorPreview = null;
private JRadioButton leftAlignRadio = null;
private JRadioButton centerAlignRadio = null;
private JRadioButton rightAlignRadio = null;
private JComboBox shapeList = null;
//----------- Static part-------------
static {
spacingBottom = 0;
spacingTop = 0;
spacingLeft = 0;
spacingRight = 0;
fontColor = "black";
fillColor = "white";
vertexShape = mxConstants.SHAPE_RECTANGLE;
graphElemetsFont = "Monospaced";
vertexTextAlign = mxConstants.ALIGN_LEFT;
loadSettings();
}
public static void loadSettings() {
String tmp = VisualGraph.config.getProperty(CONF_VERTEX_SPACING_LEFT);
if (tmp != null) {
spacingLeft = Integer.valueOf(tmp);
}
tmp = VisualGraph.config.getProperty(CONF_VERTEX_SPACING_TOP);
if (tmp != null) {
spacingTop = Integer.valueOf(tmp);
}
tmp = VisualGraph.config.getProperty(CONF_VERTEX_SPACING_RIGHT);
if (tmp != null) {
spacingRight = Integer.valueOf(tmp);
}
tmp = VisualGraph.config.getProperty(CONF_VERTEX_SPACING_BOTTOM);
if (tmp != null) {
spacingBottom = Integer.valueOf(tmp);
}
tmp = VisualGraph.config.getProperty(CONF_VERTEX_FONT_COLOR);
if (tmp != null) {
fontColor = tmp;
}
tmp = VisualGraph.config.getProperty(CONF_VERTEX_FILL_COLOR);
if (tmp != null) {
fillColor = tmp;
}
tmp = VisualGraph.config.getProperty(CONF_VERTEX_SHAPE);
if (tmp != null) {
vertexShape = tmp;
}
tmp = VisualGraph.config.getProperty(CONF_VERTEX_TEXT_ALIGN);
if (tmp != null) {
vertexTextAlign = tmp;
}
tmp = VisualGraph.config.getProperty(CONF_GRAPH_ELEMENTS_FONT);
if (tmp != null) {
graphElemetsFont = tmp;
}
generateStylesheet();
}
private static void generateStylesheet() {
Map<String, Object> style = stylesheet.getDefaultVertexStyle();
style.put(mxConstants.STYLE_SHAPE, vertexShape);
style.put(mxConstants.STYLE_FONTCOLOR, fontColor);
style.put(mxConstants.STYLE_FILLCOLOR, fillColor);
style.put(mxConstants.STYLE_SPACING_LEFT, spacingLeft);
style.put(mxConstants.STYLE_SPACING_RIGHT, spacingRight);
style.put(mxConstants.STYLE_SPACING_TOP, spacingTop);
style.put(mxConstants.STYLE_SPACING_BOTTOM, spacingBottom);
style.put(mxConstants.STYLE_ALIGN, vertexTextAlign);
style.put(mxConstants.STYLE_FONTFAMILY, graphElemetsFont);
style = stylesheet.getDefaultEdgeStyle();
style.put(mxConstants.STYLE_FONTFAMILY, graphElemetsFont);
style.put(mxConstants.STYLE_ENDARROW, mxConstants.ARROW_CLASSIC);
style.put(mxConstants.STYLE_ROUNDED, "1");
}
public static void saveSettings() {
VisualGraph.config.setProperty(CONF_GRAPH_ELEMENTS_FONT, graphElemetsFont);
VisualGraph.config.setProperty(CONF_VERTEX_FILL_COLOR, fillColor);
VisualGraph.config.setProperty(CONF_VERTEX_FONT_COLOR, fontColor);
VisualGraph.config.setProperty(CONF_VERTEX_SHAPE, vertexShape);
VisualGraph.config.setProperty(CONF_VERTEX_TEXT_ALIGN, vertexTextAlign);
VisualGraph.config.setProperty(CONF_VERTEX_SPACING_BOTTOM, String.valueOf(spacingBottom));
VisualGraph.config.setProperty(CONF_VERTEX_SPACING_TOP, String.valueOf(spacingTop));
VisualGraph.config.setProperty(CONF_VERTEX_SPACING_LEFT, String.valueOf(spacingLeft));
VisualGraph.config.setProperty(CONF_VERTEX_SPACING_RIGHT, String.valueOf(spacingRight));
}
public static mxStylesheet getStylesheet() {
return stylesheet;
}
public void install(PluginParameter parameter) throws PluginException {
JMenuItem graphSettings = new JMenuItem("Graph settings");
graphSettings.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!inited)
init();
for (JComponent c: dialogComponents) {
SwingUtilities.updateComponentTreeUI(c);
}
if (JOptionPane.showConfirmDialog(null, dialogComponents, "Graph visualization settings",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == 0) {
JGraphSettings.graphElemetsFont = fontChooser.getSelectedFontName();
JGraphSettings.spacingLeft = spacingLeftDoc.getValue();
JGraphSettings.spacingTop = spacingTopDoc.getValue();
JGraphSettings.spacingRight = spacingRightDoc.getValue();
JGraphSettings.spacingBottom = spacingBottomDoc.getValue();
JGraphSettings.fontColor = mxUtils.hexString(fontColorPreview.getBackground());
JGraphSettings.fillColor = mxUtils.hexString(vertexColorPreview.getBackground());
if (leftAlignRadio.isSelected()) {
JGraphSettings.vertexTextAlign = mxConstants.ALIGN_LEFT;
} else if (centerAlignRadio.isSelected()) {
JGraphSettings.vertexTextAlign = mxConstants.ALIGN_CENTER;
} else if (rightAlignRadio.isSelected()) {
JGraphSettings.vertexTextAlign = mxConstants.ALIGN_RIGHT;
}
JGraphSettings.vertexShape = shapeList.getSelectedItem().toString();
generateStylesheet();
saveSettings();
for (ActionListener l : listners) {
l.actionPerformed(null);
}
}
}
});
parameter.userInterface.addMenuItem(new AMenuItem(graphSettings) {
public void update(Observable o, Object arg) {
}
}, "edit");
}
public synchronized void init()
{
this.fontChooser = new FontChooserComboBox();
fontChooser.setSelectedItem(JGraphSettings.graphElemetsFont);
this.fontColorPreview = new ColorPreview();
fontColorPreview.setBackground(mxUtils.parseColor(fontColor));
JButton fontColorButton = new JButton("change");
fontColorButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Color newColor = JColorChooser.showDialog(null, "Set font color",
fontColorPreview.getBackground());
if (newColor != null) {
fontColorPreview.setBackground(newColor);
}
}
});
JPanel colorFontPane = new JPanel();
colorFontPane.setLayout(new BoxLayout(colorFontPane, BoxLayout.X_AXIS));
colorFontPane.add(new JLabel("Font color"));
colorFontPane.add(Box.createHorizontalGlue());
colorFontPane.add(fontColorPreview);
colorFontPane.add(Box.createRigidArea(new Dimension(5,0)));
colorFontPane.add(fontColorButton);
JPanel vertexSpacing = new JPanel();
vertexSpacing.setBorder(BorderFactory.createTitledBorder("Vertex spacing"));
vertexSpacing.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0);
vertexSpacing.add(new JLabel("Left"), gbc);
gbc = new GridBagConstraints(1, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0);
JTextField tf = new JTextField();
tf.setText(String.valueOf(JGraphSettings.spacingLeft));
this.spacingLeftDoc = new IntegerDocumentListner(tf, JGraphSettings.spacingLeft);
tf.getDocument().addDocumentListener(this.spacingLeftDoc);
vertexSpacing.add(tf, gbc);
gbc = new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0);
vertexSpacing.add(new JLabel("Top"), gbc);
gbc = new GridBagConstraints(1, 1, 1, 1, 1, 0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0);
tf = new JFormattedTextField();
tf.setText(String.valueOf(JGraphSettings.spacingTop));
this.spacingTopDoc = new IntegerDocumentListner(tf, JGraphSettings.spacingTop);
tf.getDocument().addDocumentListener(this.spacingTopDoc);
vertexSpacing.add(tf, gbc);
gbc = new GridBagConstraints(0, 2, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0);
vertexSpacing.add(new JLabel("Right"), gbc);
gbc = new GridBagConstraints(1, 2, 1, 1, 1, 0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0);
tf = new JFormattedTextField();
tf.setText(String.valueOf(JGraphSettings.spacingRight));
this.spacingRightDoc = new IntegerDocumentListner(tf, JGraphSettings.spacingRight);
tf.getDocument().addDocumentListener(this.spacingRightDoc);
vertexSpacing.add(tf, gbc);
gbc = new GridBagConstraints(0, 3, 1, 1, 1, 0, GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0);
vertexSpacing.add(new JLabel("Bottom"), gbc);
gbc = new GridBagConstraints(1, 3, 1, 1, 1, 0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0);
tf = new JFormattedTextField();
tf.setText(String.valueOf(JGraphSettings.spacingBottom));
this.spacingBottomDoc = new IntegerDocumentListner(tf, JGraphSettings.spacingBottom);
tf.getDocument().addDocumentListener(this.spacingBottomDoc);
vertexSpacing.add(tf, gbc);
this.vertexColorPreview = new ColorPreview();
this.vertexColorPreview.setBackground(mxUtils.parseColor(fillColor));
JButton vertexColorButton = new JButton("change");
vertexColorButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Color newColor = JColorChooser.showDialog(null, "Set font color",
vertexColorPreview.getBackground());
if (newColor != null) {
vertexColorPreview.setBackground(newColor);
}
}
});
JPanel vertexColorPane = new JPanel();
vertexColorPane.setLayout(new BoxLayout(vertexColorPane, BoxLayout.X_AXIS));
vertexColorPane.add(new JLabel("Default vertex color"));
vertexColorPane.add(Box.createHorizontalGlue());
vertexColorPane.add(this.vertexColorPreview);
vertexColorPane.add(Box.createRigidArea(new Dimension(5,0)));
vertexColorPane.add(vertexColorButton);
JPanel textAlignPane = new JPanel();
textAlignPane.setLayout(new BoxLayout(textAlignPane, BoxLayout.X_AXIS));
textAlignPane.setBorder(BorderFactory.createTitledBorder("Vertex text align"));
this.leftAlignRadio = new JRadioButton("left",
JGraphSettings.vertexTextAlign.equals(mxConstants.ALIGN_LEFT));
this.centerAlignRadio = new JRadioButton("center",
JGraphSettings.vertexTextAlign.equals(mxConstants.ALIGN_CENTER));
this.rightAlignRadio = new JRadioButton("right",
JGraphSettings.vertexTextAlign.equals(mxConstants.ALIGN_RIGHT));
textAlignPane.add(this.leftAlignRadio);
textAlignPane.add(Box.createHorizontalGlue());
textAlignPane.add(this.centerAlignRadio);
textAlignPane.add(Box.createHorizontalGlue());
textAlignPane.add(this.rightAlignRadio);
ButtonGroup group = new ButtonGroup();
group.add(leftAlignRadio);
group.add(centerAlignRadio);
group.add(rightAlignRadio);
this.shapeList = new JComboBox(new Object[] {
mxConstants.SHAPE_RECTANGLE,
mxConstants.SHAPE_ELLIPSE,
mxConstants.SHAPE_DOUBLE_ELLIPSE,
mxConstants.SHAPE_RHOMBUS,
mxConstants.SHAPE_CYLINDER,
mxConstants.SHAPE_TRIANGLE,
mxConstants.SHAPE_HEXAGON,
mxConstants.SHAPE_CLOUD
});
dialogComponents = new JComponent[] {
new JLabel("Font"),
fontChooser,
colorFontPane,
vertexSpacing,
vertexColorPane,
textAlignPane,
new JLabel("Default vertex shape"),
shapeList
};
inited = true;
}
private class IntegerDocumentListner implements DocumentListener {
private JTextField tf;
private int value;
public IntegerDocumentListner(JTextField textField, int oldvalue) {
tf = textField;
value = oldvalue;
}
public void removeUpdate(DocumentEvent e) {
String str = tf.getText();
if (str != null && str.length() > 0) {
try {
value = Integer.parseInt(str);
} catch (NumberFormatException e1) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
tf.setText(String.valueOf(value));
tf.repaint();
}
});
}
} else {
value = 0;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
tf.setText(String.valueOf(value));
tf.repaint();
}
});
}
}
public void insertUpdate(DocumentEvent e) {
removeUpdate(e);
}
public void changedUpdate(DocumentEvent e) {
}
public int getValue() {
return value;
}
}
private class ColorPreview extends JComponent {
private static final long serialVersionUID = -2276526078891878352L;
ColorPreview() {
setMinimumSize(new Dimension(24,24));
setPreferredSize(getMinimumSize());
setMaximumSize(getPreferredSize());
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(0,0,0));
Rectangle bg = new Rectangle(0, 0, getWidth(), getHeight());
bg = bg.intersection(g.getClipBounds());
g.fillRect(bg.x, bg.y, bg.width, bg.height);
g.setColor(getBackground());
bg = new Rectangle(1, 1, getWidth() - 2, getHeight() - 2);
bg = bg.intersection(g.getClipBounds());
g.fillRect(bg.x, bg.y, bg.width, bg.height);
}
}
public static void addListner(ActionListener l) {
listners.add(l);
}
public static void removeListner(ActionListener l) {
listners.remove(l);
}
}